package com.dt.platform.hr.controller;

import java.math.BigDecimal;
import java.util.*;
import com.dt.platform.proxy.hr.LearnServiceProxy;
import org.github.foxnic.web.framework.web.SuperController;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import com.github.foxnic.commons.collection.CollectorUtil;
import com.github.foxnic.dao.entity.ReferCause;
import com.github.foxnic.api.swagger.InDoc;
import org.github.foxnic.web.framework.sentinel.SentinelExceptionUtil;
import com.github.foxnic.api.swagger.ApiParamSupport;
import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.dt.platform.proxy.hr.PaperServiceProxy;
import com.dt.platform.domain.hr.meta.PaperVOMeta;
import com.dt.platform.domain.hr.Paper;
import com.dt.platform.domain.hr.PaperVO;
import com.github.foxnic.api.transter.Result;
import com.github.foxnic.dao.data.SaveMode;
import com.github.foxnic.dao.excel.ExcelWriter;
import com.github.foxnic.springboot.web.DownloadUtil;
import com.github.foxnic.dao.data.PagedList;
import java.util.Date;
import java.sql.Timestamp;
import com.github.foxnic.api.error.ErrorDesc;
import com.github.foxnic.commons.io.StreamUtil;
import java.util.Map;
import com.github.foxnic.dao.excel.ValidateResult;
import java.io.InputStream;
import com.dt.platform.domain.hr.meta.PaperMeta;
import com.dt.platform.domain.hr.PaperQuestion;
import com.dt.platform.domain.hr.Learn;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiImplicitParam;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.dt.platform.hr.service.IPaperService;
import com.github.foxnic.api.validate.annotations.NotNull;

/**
 * <p>
 * 考试试卷接口控制器
 * </p>
 * @author 金杰 , maillank@qq.com
 * @since 2024-09-14 11:41:34
 */
@InDoc
@Api(tags = "考试试卷")
@RestController("HrPaperController")
public class PaperController extends SuperController {

    @Autowired
    private IPaperService paperService;

    /**
     * 添加考试试卷
     */
    @ApiOperation(value = "添加考试试卷")
    @ApiImplicitParams({
		@ApiImplicitParam(name = PaperVOMeta.ID, value = "主键", required = true, dataTypeClass = String.class, example = "590126512513093"),
		@ApiImplicitParam(name = PaperVOMeta.NAME, value = "考试名称", required = false, dataTypeClass = String.class, example = "本次考试"),
		@ApiImplicitParam(name = PaperVOMeta.STATUS, value = "状态", required = false, dataTypeClass = String.class, example = "enable"),
		@ApiImplicitParam(name = PaperVOMeta.LEARN_ID, value = "学习课件", required = false, dataTypeClass = String.class),
		@ApiImplicitParam(name = PaperVOMeta.IF_LEARN, value = "关联学习", required = false, dataTypeClass = String.class),
		@ApiImplicitParam(name = PaperVOMeta.SDATE, value = "开始时间", required = false, dataTypeClass = Date.class, example = "2024-09-02 12:00:00"),
		@ApiImplicitParam(name = PaperVOMeta.EDATE, value = "结束时间", required = false, dataTypeClass = Date.class, example = "2024-09-27 12:00:00"),
		@ApiImplicitParam(name = PaperVOMeta.COST, value = "考试用时", required = false, dataTypeClass = Integer.class, example = "30"),
		@ApiImplicitParam(name = PaperVOMeta.NOTES, value = "备注", required = false, dataTypeClass = String.class),
		@ApiImplicitParam(name = PaperVOMeta.PAPER_FORM_ID, value = "试卷", required = false, dataTypeClass = String.class),
		@ApiImplicitParam(name = PaperVOMeta.UPDATE_BY, value = "修改人ID", required = false, dataTypeClass = String.class),
		@ApiImplicitParam(name = PaperVOMeta.MODE, value = "答题模式", required = false, dataTypeClass = String.class),
		@ApiImplicitParam(name = PaperVOMeta.LEARN_PAPER_ID, value = "选择题库", required = false, dataTypeClass = String.class),
		@ApiImplicitParam(name = PaperVOMeta.JUDGE_CNT, value = "判断题数", required = false, dataTypeClass = Integer.class),
		@ApiImplicitParam(name = PaperVOMeta.RADIO_CNT, value = "单选题数", required = false, dataTypeClass = Integer.class),
		@ApiImplicitParam(name = PaperVOMeta.CHOICE_CNT, value = "多选题数", required = false, dataTypeClass = Integer.class),
		@ApiImplicitParam(name = PaperVOMeta.TEXTAREA_CNT, value = "填空题数", required = false, dataTypeClass = Integer.class),
		@ApiImplicitParam(name = PaperVOMeta.CHOICE_SCORE, value = "多选题分", required = false, dataTypeClass = BigDecimal.class),
		@ApiImplicitParam(name = PaperVOMeta.JUDGE_SCORE, value = "判断题分", required = false, dataTypeClass = BigDecimal.class),
		@ApiImplicitParam(name = PaperVOMeta.OWNER_CODE, value = "所属类型", required = false, dataTypeClass = String.class),
		@ApiImplicitParam(name = PaperVOMeta.OWNER_ID, value = "所属", required = false, dataTypeClass = String.class),
		@ApiImplicitParam(name = PaperVOMeta.RADIO_SCORE, value = "单选题分", required = false, dataTypeClass = BigDecimal.class),
		@ApiImplicitParam(name = PaperVOMeta.TEXTAREA_SCORE, value = "填空题分", required = false, dataTypeClass = BigDecimal.class),
		@ApiImplicitParam(name = PaperVOMeta.FIX_ENABLE, value = "固定模式", required = false, dataTypeClass = String.class),
		@ApiImplicitParam(name = PaperVOMeta.RAND_ENABLE, value = "抽题模式", required = false, dataTypeClass = String.class),
		@ApiImplicitParam(name = PaperVOMeta.SCORE_CONF, value = "分数设置", required = false, dataTypeClass = String.class),
		@ApiImplicitParam(name = PaperVOMeta.TOTAL_SCORE, value = "总分", required = false, dataTypeClass = BigDecimal.class),
		@ApiImplicitParam(name = PaperVOMeta.PASS_SCORE, value = "通过分", required = false, dataTypeClass = BigDecimal.class),
		@ApiImplicitParam(name = PaperVOMeta.JUDGE_R_CNT, value = "判断题数", required = false, dataTypeClass = Integer.class),
		@ApiImplicitParam(name = PaperVOMeta.RADIO_R_CNT, value = "单选题数", required = false, dataTypeClass = Integer.class),
		@ApiImplicitParam(name = PaperVOMeta.CHOICE_R_CNT, value = "多选题数", required = false, dataTypeClass = Integer.class),
		@ApiImplicitParam(name = PaperVOMeta.TEXTAREA_R_CNT, value = "填空题数", required = false, dataTypeClass = Integer.class),
		@ApiImplicitParam(name = PaperVOMeta.QUESTION_MODE, value = "选题策略", required = false, dataTypeClass = String.class),
		@ApiImplicitParam(name = PaperVOMeta.QUESTION_R_CNT, value = "题目总数", required = false, dataTypeClass = Integer.class)
	})
    @ApiParamSupport(ignoreDBTreatyProperties = true, ignoreDefaultVoProperties = true, ignorePrimaryKey = true)
    @ApiOperationSupport(order = 1, author = "金杰 , maillank@qq.com")
    @SentinelResource(value = PaperServiceProxy.INSERT, blockHandlerClass = { SentinelExceptionUtil.class }, blockHandler = SentinelExceptionUtil.HANDLER)
    @PostMapping(PaperServiceProxy.INSERT)
    public Result insert(PaperVO paperVO) {
        Result result = paperService.insert(paperVO, false);
        return result;
    }

    /**
     * 删除考试试卷
     */
    @ApiOperation(value = "删除考试试卷")
    @ApiImplicitParams({
		@ApiImplicitParam(name = PaperVOMeta.ID, value = "主键", required = true, dataTypeClass = String.class, example = "590126512513093")
	})
    @ApiOperationSupport(order = 2, author = "金杰 , maillank@qq.com")
    @SentinelResource(value = PaperServiceProxy.DELETE, blockHandlerClass = { SentinelExceptionUtil.class }, blockHandler = SentinelExceptionUtil.HANDLER)
    @PostMapping(PaperServiceProxy.DELETE)
    public Result deleteById(String id) {
        this.validator().asserts(id).require("缺少id值");
        if (this.validator().failure()) {
            return this.validator().getFirstResult();
        }
        // 引用校验
        ReferCause cause = paperService.hasRefers(id);
        // 判断是否可以删除
        this.validator().asserts(cause.hasRefer()).requireEqual("不允许删除当前记录：" + cause.message(), false);
        if (this.validator().failure()) {
            return this.validator().getFirstResult().messageLevel4Confirm();
        }
        Result result = paperService.deleteByIdLogical(id);
        return result;
    }
	/**
	 * 考试试卷
	 */
	@ApiOperation(value = "考试试卷")

	@ApiOperationSupport(order = 2, author = "金杰 , maillank@qq.com")
	@SentinelResource(value = PaperServiceProxy.EVALUATE_PAPERS, blockHandlerClass = { SentinelExceptionUtil.class }, blockHandler = SentinelExceptionUtil.HANDLER)
	@PostMapping(PaperServiceProxy.EVALUATE_PAPERS)
	public Result evaluatePapers(List<String> ids) {
		return paperService.evaluatePapers(ids);
	}


	/**
	 * 生成试卷
	 */
	@ApiOperation(value = "生成试卷")
	@ApiOperationSupport(order = 6, author = "金杰 , maillank@qq.com")
	@SentinelResource(value = PaperServiceProxy.CREATE_PAPER, blockHandlerClass = { SentinelExceptionUtil.class }, blockHandler = SentinelExceptionUtil.HANDLER)
	@PostMapping(PaperServiceProxy.CREATE_PAPER)
	public Result createPaper(String id) {
		return paperService.createPaper(id);
	}


	/**
     * 批量删除考试试卷 <br>
     * 联合主键时，请自行调整实现
     */
    @ApiOperation(value = "批量删除考试试卷")
    @ApiImplicitParams({
		@ApiImplicitParam(name = PaperVOMeta.IDS, value = "主键清单", required = true, dataTypeClass = List.class, example = "[1,3,4]")
	})
    @ApiOperationSupport(order = 3, author = "金杰 , maillank@qq.com")
    @SentinelResource(value = PaperServiceProxy.DELETE_BY_IDS, blockHandlerClass = { SentinelExceptionUtil.class }, blockHandler = SentinelExceptionUtil.HANDLER)
    @PostMapping(PaperServiceProxy.DELETE_BY_IDS)
    public Result deleteByIds(List<String> ids) {
        // 参数校验
        this.validator().asserts(ids).require("缺少ids参数");
        if (this.validator().failure()) {
            return this.validator().getFirstResult();
        }
        // 查询引用
        Map<String, ReferCause> causeMap = paperService.hasRefers(ids);
        // 收集可以删除的ID值
        List<String> canDeleteIds = new ArrayList<>();
        for (Map.Entry<String, ReferCause> e : causeMap.entrySet()) {
            if (!e.getValue().hasRefer()) {
                canDeleteIds.add(e.getKey());
            }
        }
        // 执行删除
        if (canDeleteIds.isEmpty()) {
            // 如果没有一行可以被删除
            return ErrorDesc.failure().message("无法删除您选中的数据行：").data(0).addErrors(CollectorUtil.collectArray(CollectorUtil.filter(causeMap.values(), (e) -> {
                return e.hasRefer();
            }), ReferCause::message, String.class)).messageLevel4Confirm();
        } else if (canDeleteIds.size() == ids.size()) {
            // 如果全部可以删除
            Result result = paperService.deleteByIdsLogical(canDeleteIds);
            return result;
        } else if (canDeleteIds.size() > 0 && canDeleteIds.size() < ids.size()) {
            // 如果部分行可以删除
            Result result = paperService.deleteByIdsLogical(canDeleteIds);
            if (result.failure()) {
                return result;
            } else {
                return ErrorDesc.success().message("已删除 " + canDeleteIds.size() + " 行，但另有 " + (ids.size() - canDeleteIds.size()) + " 行数据无法删除").data(canDeleteIds.size()).addErrors(CollectorUtil.collectArray(CollectorUtil.filter(causeMap.values(), (e) -> {
                    return e.hasRefer();
                }), ReferCause::message, String.class)).messageLevel4Confirm();
            }
        } else {
            // 理论上，这个分支不存在
            return ErrorDesc.success().message("数据删除未处理");
        }
    }

    /**
     * 更新考试试卷
     */
    @ApiOperation(value = "更新考试试卷")
    @ApiImplicitParams({
		@ApiImplicitParam(name = PaperVOMeta.ID, value = "主键", required = true, dataTypeClass = String.class, example = "590126512513093"),
		@ApiImplicitParam(name = PaperVOMeta.NAME, value = "考试名称", required = false, dataTypeClass = String.class, example = "本次考试"),
		@ApiImplicitParam(name = PaperVOMeta.STATUS, value = "状态", required = false, dataTypeClass = String.class, example = "enable"),
		@ApiImplicitParam(name = PaperVOMeta.LEARN_ID, value = "学习课件", required = false, dataTypeClass = String.class),
		@ApiImplicitParam(name = PaperVOMeta.IF_LEARN, value = "关联学习", required = false, dataTypeClass = String.class),
		@ApiImplicitParam(name = PaperVOMeta.SDATE, value = "开始时间", required = false, dataTypeClass = Date.class, example = "2024-09-02 12:00:00"),
		@ApiImplicitParam(name = PaperVOMeta.EDATE, value = "结束时间", required = false, dataTypeClass = Date.class, example = "2024-09-27 12:00:00"),
		@ApiImplicitParam(name = PaperVOMeta.COST, value = "考试用时", required = false, dataTypeClass = Integer.class, example = "30"),
		@ApiImplicitParam(name = PaperVOMeta.NOTES, value = "备注", required = false, dataTypeClass = String.class),
		@ApiImplicitParam(name = PaperVOMeta.PAPER_FORM_ID, value = "试卷", required = false, dataTypeClass = String.class),
		@ApiImplicitParam(name = PaperVOMeta.UPDATE_BY, value = "修改人ID", required = false, dataTypeClass = String.class),
		@ApiImplicitParam(name = PaperVOMeta.MODE, value = "答题模式", required = false, dataTypeClass = String.class),
		@ApiImplicitParam(name = PaperVOMeta.LEARN_PAPER_ID, value = "选择题库", required = false, dataTypeClass = String.class),
		@ApiImplicitParam(name = PaperVOMeta.JUDGE_CNT, value = "判断题数", required = false, dataTypeClass = Integer.class),
		@ApiImplicitParam(name = PaperVOMeta.RADIO_CNT, value = "单选题数", required = false, dataTypeClass = Integer.class),
		@ApiImplicitParam(name = PaperVOMeta.CHOICE_CNT, value = "多选题数", required = false, dataTypeClass = Integer.class),
		@ApiImplicitParam(name = PaperVOMeta.TEXTAREA_CNT, value = "填空题数", required = false, dataTypeClass = Integer.class),
		@ApiImplicitParam(name = PaperVOMeta.CHOICE_SCORE, value = "多选题分", required = false, dataTypeClass = BigDecimal.class),
		@ApiImplicitParam(name = PaperVOMeta.JUDGE_SCORE, value = "判断题分", required = false, dataTypeClass = BigDecimal.class),
		@ApiImplicitParam(name = PaperVOMeta.OWNER_CODE, value = "所属类型", required = false, dataTypeClass = String.class),
		@ApiImplicitParam(name = PaperVOMeta.OWNER_ID, value = "所属", required = false, dataTypeClass = String.class),
		@ApiImplicitParam(name = PaperVOMeta.RADIO_SCORE, value = "单选题分", required = false, dataTypeClass = BigDecimal.class),
		@ApiImplicitParam(name = PaperVOMeta.TEXTAREA_SCORE, value = "填空题分", required = false, dataTypeClass = BigDecimal.class),
		@ApiImplicitParam(name = PaperVOMeta.FIX_ENABLE, value = "固定模式", required = false, dataTypeClass = String.class),
		@ApiImplicitParam(name = PaperVOMeta.RAND_ENABLE, value = "抽题模式", required = false, dataTypeClass = String.class),
		@ApiImplicitParam(name = PaperVOMeta.SCORE_CONF, value = "分数设置", required = false, dataTypeClass = String.class),
		@ApiImplicitParam(name = PaperVOMeta.TOTAL_SCORE, value = "总分", required = false, dataTypeClass = BigDecimal.class),
		@ApiImplicitParam(name = PaperVOMeta.PASS_SCORE, value = "通过分", required = false, dataTypeClass = BigDecimal.class),
		@ApiImplicitParam(name = PaperVOMeta.JUDGE_R_CNT, value = "判断题数", required = false, dataTypeClass = Integer.class),
		@ApiImplicitParam(name = PaperVOMeta.RADIO_R_CNT, value = "单选题数", required = false, dataTypeClass = Integer.class),
		@ApiImplicitParam(name = PaperVOMeta.CHOICE_R_CNT, value = "多选题数", required = false, dataTypeClass = Integer.class),
		@ApiImplicitParam(name = PaperVOMeta.TEXTAREA_R_CNT, value = "填空题数", required = false, dataTypeClass = Integer.class),
		@ApiImplicitParam(name = PaperVOMeta.QUESTION_MODE, value = "选题策略", required = false, dataTypeClass = String.class),
		@ApiImplicitParam(name = PaperVOMeta.QUESTION_R_CNT, value = "题目总数", required = false, dataTypeClass = Integer.class)
	})
    @ApiParamSupport(ignoreDBTreatyProperties = true, ignoreDefaultVoProperties = true)
    @ApiOperationSupport(order = 4, author = "金杰 , maillank@qq.com", ignoreParameters = { PaperVOMeta.PAGE_INDEX, PaperVOMeta.PAGE_SIZE, PaperVOMeta.SEARCH_FIELD, PaperVOMeta.FUZZY_FIELD, PaperVOMeta.SEARCH_VALUE, PaperVOMeta.DIRTY_FIELDS, PaperVOMeta.SORT_FIELD, PaperVOMeta.SORT_TYPE, PaperVOMeta.DATA_ORIGIN, PaperVOMeta.QUERY_LOGIC, PaperVOMeta.REQUEST_ACTION, PaperVOMeta.IDS })
    @SentinelResource(value = PaperServiceProxy.UPDATE, blockHandlerClass = { SentinelExceptionUtil.class }, blockHandler = SentinelExceptionUtil.HANDLER)
    @PostMapping(PaperServiceProxy.UPDATE)
    public Result update(PaperVO paperVO) {
        Result result = paperService.update(paperVO, SaveMode.DIRTY_OR_NOT_NULL_FIELDS, false);
        return result;
    }

    /**
     * 保存考试试卷
     */
    @ApiOperation(value = "保存考试试卷")
    @ApiImplicitParams({
		@ApiImplicitParam(name = PaperVOMeta.ID, value = "主键", required = true, dataTypeClass = String.class, example = "590126512513093"),
		@ApiImplicitParam(name = PaperVOMeta.NAME, value = "考试名称", required = false, dataTypeClass = String.class, example = "本次考试"),
		@ApiImplicitParam(name = PaperVOMeta.STATUS, value = "状态", required = false, dataTypeClass = String.class, example = "enable"),
		@ApiImplicitParam(name = PaperVOMeta.LEARN_ID, value = "学习课件", required = false, dataTypeClass = String.class),
		@ApiImplicitParam(name = PaperVOMeta.IF_LEARN, value = "关联学习", required = false, dataTypeClass = String.class),
		@ApiImplicitParam(name = PaperVOMeta.SDATE, value = "开始时间", required = false, dataTypeClass = Date.class, example = "2024-09-02 12:00:00"),
		@ApiImplicitParam(name = PaperVOMeta.EDATE, value = "结束时间", required = false, dataTypeClass = Date.class, example = "2024-09-27 12:00:00"),
		@ApiImplicitParam(name = PaperVOMeta.COST, value = "考试用时", required = false, dataTypeClass = Integer.class, example = "30"),
		@ApiImplicitParam(name = PaperVOMeta.NOTES, value = "备注", required = false, dataTypeClass = String.class),
		@ApiImplicitParam(name = PaperVOMeta.PAPER_FORM_ID, value = "试卷", required = false, dataTypeClass = String.class),
		@ApiImplicitParam(name = PaperVOMeta.UPDATE_BY, value = "修改人ID", required = false, dataTypeClass = String.class),
		@ApiImplicitParam(name = PaperVOMeta.MODE, value = "答题模式", required = false, dataTypeClass = String.class),
		@ApiImplicitParam(name = PaperVOMeta.LEARN_PAPER_ID, value = "选择题库", required = false, dataTypeClass = String.class),
		@ApiImplicitParam(name = PaperVOMeta.JUDGE_CNT, value = "判断题数", required = false, dataTypeClass = Integer.class),
		@ApiImplicitParam(name = PaperVOMeta.RADIO_CNT, value = "单选题数", required = false, dataTypeClass = Integer.class),
		@ApiImplicitParam(name = PaperVOMeta.CHOICE_CNT, value = "多选题数", required = false, dataTypeClass = Integer.class),
		@ApiImplicitParam(name = PaperVOMeta.TEXTAREA_CNT, value = "填空题数", required = false, dataTypeClass = Integer.class),
		@ApiImplicitParam(name = PaperVOMeta.CHOICE_SCORE, value = "多选题分", required = false, dataTypeClass = BigDecimal.class),
		@ApiImplicitParam(name = PaperVOMeta.JUDGE_SCORE, value = "判断题分", required = false, dataTypeClass = BigDecimal.class),
		@ApiImplicitParam(name = PaperVOMeta.OWNER_CODE, value = "所属类型", required = false, dataTypeClass = String.class),
		@ApiImplicitParam(name = PaperVOMeta.OWNER_ID, value = "所属", required = false, dataTypeClass = String.class),
		@ApiImplicitParam(name = PaperVOMeta.RADIO_SCORE, value = "单选题分", required = false, dataTypeClass = BigDecimal.class),
		@ApiImplicitParam(name = PaperVOMeta.TEXTAREA_SCORE, value = "填空题分", required = false, dataTypeClass = BigDecimal.class),
		@ApiImplicitParam(name = PaperVOMeta.FIX_ENABLE, value = "固定模式", required = false, dataTypeClass = String.class),
		@ApiImplicitParam(name = PaperVOMeta.RAND_ENABLE, value = "抽题模式", required = false, dataTypeClass = String.class),
		@ApiImplicitParam(name = PaperVOMeta.SCORE_CONF, value = "分数设置", required = false, dataTypeClass = String.class),
		@ApiImplicitParam(name = PaperVOMeta.TOTAL_SCORE, value = "总分", required = false, dataTypeClass = BigDecimal.class),
		@ApiImplicitParam(name = PaperVOMeta.PASS_SCORE, value = "通过分", required = false, dataTypeClass = BigDecimal.class),
		@ApiImplicitParam(name = PaperVOMeta.JUDGE_R_CNT, value = "判断题数", required = false, dataTypeClass = Integer.class),
		@ApiImplicitParam(name = PaperVOMeta.RADIO_R_CNT, value = "单选题数", required = false, dataTypeClass = Integer.class),
		@ApiImplicitParam(name = PaperVOMeta.CHOICE_R_CNT, value = "多选题数", required = false, dataTypeClass = Integer.class),
		@ApiImplicitParam(name = PaperVOMeta.TEXTAREA_R_CNT, value = "填空题数", required = false, dataTypeClass = Integer.class),
		@ApiImplicitParam(name = PaperVOMeta.QUESTION_MODE, value = "选题策略", required = false, dataTypeClass = String.class),
		@ApiImplicitParam(name = PaperVOMeta.QUESTION_R_CNT, value = "题目总数", required = false, dataTypeClass = Integer.class)
	})
    @ApiParamSupport(ignoreDBTreatyProperties = true, ignoreDefaultVoProperties = true)
    @ApiOperationSupport(order = 5, ignoreParameters = { PaperVOMeta.PAGE_INDEX, PaperVOMeta.PAGE_SIZE, PaperVOMeta.SEARCH_FIELD, PaperVOMeta.FUZZY_FIELD, PaperVOMeta.SEARCH_VALUE, PaperVOMeta.DIRTY_FIELDS, PaperVOMeta.SORT_FIELD, PaperVOMeta.SORT_TYPE, PaperVOMeta.DATA_ORIGIN, PaperVOMeta.QUERY_LOGIC, PaperVOMeta.REQUEST_ACTION, PaperVOMeta.IDS })
    @SentinelResource(value = PaperServiceProxy.SAVE, blockHandlerClass = { SentinelExceptionUtil.class }, blockHandler = SentinelExceptionUtil.HANDLER)
    @PostMapping(PaperServiceProxy.SAVE)
    public Result save(PaperVO paperVO) {
        Result result = paperService.save(paperVO, SaveMode.DIRTY_OR_NOT_NULL_FIELDS, false);
        return result;
    }

    /**
     * 开始
     */
    @ApiOperation(value = "开始")
    @ApiOperationSupport(order = 2, author = "金杰 , maillank@qq.com")
    @SentinelResource(value = PaperServiceProxy.ANSWER, blockHandlerClass = { SentinelExceptionUtil.class }, blockHandler = SentinelExceptionUtil.HANDLER)
    @PostMapping(PaperServiceProxy.ANSWER)
    public Result answer(String taskId, String questionRelId, String value) {
        return paperService.answer(taskId, questionRelId, value);
    }

    /**
     * 完成
     */
    @ApiOperation(value = "完成")
    @ApiOperationSupport(order = 2, author = "金杰 , maillank@qq.com")
    @SentinelResource(value = PaperServiceProxy.FINISH, blockHandlerClass = { SentinelExceptionUtil.class }, blockHandler = SentinelExceptionUtil.HANDLER)
    @PostMapping(PaperServiceProxy.FINISH)
    public Result finish(String taskId) {
        return paperService.finish(taskId);
    }

    @ApiOperation(value = "获得考试")
    @ApiOperationSupport(order = 2, author = "金杰 , maillank@qq.com")
    @SentinelResource(value = PaperServiceProxy.GET_PAPER, blockHandlerClass = { SentinelExceptionUtil.class }, blockHandler = SentinelExceptionUtil.HANDLER)
    @PostMapping(PaperServiceProxy.GET_PAPER)
    public Result getPaper(String id, String taskId) {
        return paperService.getPaper(id, taskId);
    }

    @ApiOperation(value = "获得题目")
    @ApiOperationSupport(order = 2, author = "金杰 , maillank@qq.com")
    @SentinelResource(value = PaperServiceProxy.GET_PAPER_QUESTION, blockHandlerClass = { SentinelExceptionUtil.class }, blockHandler = SentinelExceptionUtil.HANDLER)
    @PostMapping(PaperServiceProxy.GET_PAPER_QUESTION)
    public Result getPaperQuestion(String id, String taskId) {
        return paperService.getPaperQuestion(id, taskId);
    }

    /**
     * 获取考试试卷
     */
    @ApiOperation(value = "获取考试试卷")
    @ApiImplicitParams({
		@ApiImplicitParam(name = PaperVOMeta.ID, value = "主键", required = true, dataTypeClass = String.class, example = "1")
	})
    @ApiOperationSupport(order = 6, author = "金杰 , maillank@qq.com")
    @SentinelResource(value = PaperServiceProxy.GET_BY_ID, blockHandlerClass = { SentinelExceptionUtil.class }, blockHandler = SentinelExceptionUtil.HANDLER)
    @PostMapping(PaperServiceProxy.GET_BY_ID)
    public Result<Paper> getById(String id) {
        Result<Paper> result = new Result<>();
        Paper paper = paperService.getById(id);
        // join 关联的对象
        paperService.dao().fill(paper).with(PaperMeta.LEARN).with(PaperMeta.LEARN_PAPER).execute();
        result.success(true).data(paper);
        return result;
    }

    /**
     * 批量获取考试试卷 <br>
     * 联合主键时，请自行调整实现
     */
    @ApiOperation(value = "批量获取考试试卷")
    @ApiImplicitParams({
		@ApiImplicitParam(name = PaperVOMeta.IDS, value = "主键清单", required = true, dataTypeClass = List.class, example = "[1,3,4]")
	})
    @ApiOperationSupport(order = 3, author = "金杰 , maillank@qq.com")
    @SentinelResource(value = PaperServiceProxy.GET_BY_IDS, blockHandlerClass = { SentinelExceptionUtil.class }, blockHandler = SentinelExceptionUtil.HANDLER)
    @PostMapping(PaperServiceProxy.GET_BY_IDS)
    public Result<List<Paper>> getByIds(List<String> ids) {
        Result<List<Paper>> result = new Result<>();
        List<Paper> list = paperService.queryListByIds(ids);
        result.success(true).data(list);
        return result;
    }

    /**
     * 查询考试试卷
     */
    @ApiOperation(value = "查询考试试卷")
    @ApiImplicitParams({
		@ApiImplicitParam(name = PaperVOMeta.ID, value = "主键", required = true, dataTypeClass = String.class, example = "590126512513093"),
		@ApiImplicitParam(name = PaperVOMeta.NAME, value = "考试名称", required = false, dataTypeClass = String.class, example = "本次考试"),
		@ApiImplicitParam(name = PaperVOMeta.STATUS, value = "状态", required = false, dataTypeClass = String.class, example = "enable"),
		@ApiImplicitParam(name = PaperVOMeta.LEARN_ID, value = "学习课件", required = false, dataTypeClass = String.class),
		@ApiImplicitParam(name = PaperVOMeta.IF_LEARN, value = "关联学习", required = false, dataTypeClass = String.class),
		@ApiImplicitParam(name = PaperVOMeta.SDATE, value = "开始时间", required = false, dataTypeClass = Date.class, example = "2024-09-02 12:00:00"),
		@ApiImplicitParam(name = PaperVOMeta.EDATE, value = "结束时间", required = false, dataTypeClass = Date.class, example = "2024-09-27 12:00:00"),
		@ApiImplicitParam(name = PaperVOMeta.COST, value = "考试用时", required = false, dataTypeClass = Integer.class, example = "30"),
		@ApiImplicitParam(name = PaperVOMeta.NOTES, value = "备注", required = false, dataTypeClass = String.class),
		@ApiImplicitParam(name = PaperVOMeta.PAPER_FORM_ID, value = "试卷", required = false, dataTypeClass = String.class),
		@ApiImplicitParam(name = PaperVOMeta.UPDATE_BY, value = "修改人ID", required = false, dataTypeClass = String.class),
		@ApiImplicitParam(name = PaperVOMeta.MODE, value = "答题模式", required = false, dataTypeClass = String.class),
		@ApiImplicitParam(name = PaperVOMeta.LEARN_PAPER_ID, value = "选择题库", required = false, dataTypeClass = String.class),
		@ApiImplicitParam(name = PaperVOMeta.JUDGE_CNT, value = "判断题数", required = false, dataTypeClass = Integer.class),
		@ApiImplicitParam(name = PaperVOMeta.RADIO_CNT, value = "单选题数", required = false, dataTypeClass = Integer.class),
		@ApiImplicitParam(name = PaperVOMeta.CHOICE_CNT, value = "多选题数", required = false, dataTypeClass = Integer.class),
		@ApiImplicitParam(name = PaperVOMeta.TEXTAREA_CNT, value = "填空题数", required = false, dataTypeClass = Integer.class),
		@ApiImplicitParam(name = PaperVOMeta.CHOICE_SCORE, value = "多选题分", required = false, dataTypeClass = BigDecimal.class),
		@ApiImplicitParam(name = PaperVOMeta.JUDGE_SCORE, value = "判断题分", required = false, dataTypeClass = BigDecimal.class),
		@ApiImplicitParam(name = PaperVOMeta.OWNER_CODE, value = "所属类型", required = false, dataTypeClass = String.class),
		@ApiImplicitParam(name = PaperVOMeta.OWNER_ID, value = "所属", required = false, dataTypeClass = String.class),
		@ApiImplicitParam(name = PaperVOMeta.RADIO_SCORE, value = "单选题分", required = false, dataTypeClass = BigDecimal.class),
		@ApiImplicitParam(name = PaperVOMeta.TEXTAREA_SCORE, value = "填空题分", required = false, dataTypeClass = BigDecimal.class),
		@ApiImplicitParam(name = PaperVOMeta.FIX_ENABLE, value = "固定模式", required = false, dataTypeClass = String.class),
		@ApiImplicitParam(name = PaperVOMeta.RAND_ENABLE, value = "抽题模式", required = false, dataTypeClass = String.class),
		@ApiImplicitParam(name = PaperVOMeta.SCORE_CONF, value = "分数设置", required = false, dataTypeClass = String.class),
		@ApiImplicitParam(name = PaperVOMeta.TOTAL_SCORE, value = "总分", required = false, dataTypeClass = BigDecimal.class),
		@ApiImplicitParam(name = PaperVOMeta.PASS_SCORE, value = "通过分", required = false, dataTypeClass = BigDecimal.class),
		@ApiImplicitParam(name = PaperVOMeta.JUDGE_R_CNT, value = "判断题数", required = false, dataTypeClass = Integer.class),
		@ApiImplicitParam(name = PaperVOMeta.RADIO_R_CNT, value = "单选题数", required = false, dataTypeClass = Integer.class),
		@ApiImplicitParam(name = PaperVOMeta.CHOICE_R_CNT, value = "多选题数", required = false, dataTypeClass = Integer.class),
		@ApiImplicitParam(name = PaperVOMeta.TEXTAREA_R_CNT, value = "填空题数", required = false, dataTypeClass = Integer.class),
		@ApiImplicitParam(name = PaperVOMeta.QUESTION_MODE, value = "选题策略", required = false, dataTypeClass = String.class),
		@ApiImplicitParam(name = PaperVOMeta.QUESTION_R_CNT, value = "题目总数", required = false, dataTypeClass = Integer.class)
	})
    @ApiOperationSupport(order = 5, author = "金杰 , maillank@qq.com", ignoreParameters = { PaperVOMeta.PAGE_INDEX, PaperVOMeta.PAGE_SIZE })
    @SentinelResource(value = PaperServiceProxy.QUERY_LIST, blockHandlerClass = { SentinelExceptionUtil.class }, blockHandler = SentinelExceptionUtil.HANDLER)
    @PostMapping(PaperServiceProxy.QUERY_LIST)
    public Result<List<Paper>> queryList(PaperVO sample) {
        Result<List<Paper>> result = new Result<>();
        List<Paper> list = paperService.queryList(sample);
        result.success(true).data(list);
        return result;
    }

    /**
     * 分页查询考试试卷
     */
    @ApiOperation(value = "分页查询考试试卷")
    @ApiImplicitParams({
		@ApiImplicitParam(name = PaperVOMeta.ID, value = "主键", required = true, dataTypeClass = String.class, example = "590126512513093"),
		@ApiImplicitParam(name = PaperVOMeta.NAME, value = "考试名称", required = false, dataTypeClass = String.class, example = "本次考试"),
		@ApiImplicitParam(name = PaperVOMeta.STATUS, value = "状态", required = false, dataTypeClass = String.class, example = "enable"),
		@ApiImplicitParam(name = PaperVOMeta.LEARN_ID, value = "学习课件", required = false, dataTypeClass = String.class),
		@ApiImplicitParam(name = PaperVOMeta.IF_LEARN, value = "关联学习", required = false, dataTypeClass = String.class),
		@ApiImplicitParam(name = PaperVOMeta.SDATE, value = "开始时间", required = false, dataTypeClass = Date.class, example = "2024-09-02 12:00:00"),
		@ApiImplicitParam(name = PaperVOMeta.EDATE, value = "结束时间", required = false, dataTypeClass = Date.class, example = "2024-09-27 12:00:00"),
		@ApiImplicitParam(name = PaperVOMeta.COST, value = "考试用时", required = false, dataTypeClass = Integer.class, example = "30"),
		@ApiImplicitParam(name = PaperVOMeta.NOTES, value = "备注", required = false, dataTypeClass = String.class),
		@ApiImplicitParam(name = PaperVOMeta.PAPER_FORM_ID, value = "试卷", required = false, dataTypeClass = String.class),
		@ApiImplicitParam(name = PaperVOMeta.UPDATE_BY, value = "修改人ID", required = false, dataTypeClass = String.class),
		@ApiImplicitParam(name = PaperVOMeta.MODE, value = "答题模式", required = false, dataTypeClass = String.class),
		@ApiImplicitParam(name = PaperVOMeta.LEARN_PAPER_ID, value = "选择题库", required = false, dataTypeClass = String.class),
		@ApiImplicitParam(name = PaperVOMeta.JUDGE_CNT, value = "判断题数", required = false, dataTypeClass = Integer.class),
		@ApiImplicitParam(name = PaperVOMeta.RADIO_CNT, value = "单选题数", required = false, dataTypeClass = Integer.class),
		@ApiImplicitParam(name = PaperVOMeta.CHOICE_CNT, value = "多选题数", required = false, dataTypeClass = Integer.class),
		@ApiImplicitParam(name = PaperVOMeta.TEXTAREA_CNT, value = "填空题数", required = false, dataTypeClass = Integer.class),
		@ApiImplicitParam(name = PaperVOMeta.CHOICE_SCORE, value = "多选题分", required = false, dataTypeClass = BigDecimal.class),
		@ApiImplicitParam(name = PaperVOMeta.JUDGE_SCORE, value = "判断题分", required = false, dataTypeClass = BigDecimal.class),
		@ApiImplicitParam(name = PaperVOMeta.OWNER_CODE, value = "所属类型", required = false, dataTypeClass = String.class),
		@ApiImplicitParam(name = PaperVOMeta.OWNER_ID, value = "所属", required = false, dataTypeClass = String.class),
		@ApiImplicitParam(name = PaperVOMeta.RADIO_SCORE, value = "单选题分", required = false, dataTypeClass = BigDecimal.class),
		@ApiImplicitParam(name = PaperVOMeta.TEXTAREA_SCORE, value = "填空题分", required = false, dataTypeClass = BigDecimal.class),
		@ApiImplicitParam(name = PaperVOMeta.FIX_ENABLE, value = "固定模式", required = false, dataTypeClass = String.class),
		@ApiImplicitParam(name = PaperVOMeta.RAND_ENABLE, value = "抽题模式", required = false, dataTypeClass = String.class),
		@ApiImplicitParam(name = PaperVOMeta.SCORE_CONF, value = "分数设置", required = false, dataTypeClass = String.class),
		@ApiImplicitParam(name = PaperVOMeta.TOTAL_SCORE, value = "总分", required = false, dataTypeClass = BigDecimal.class),
		@ApiImplicitParam(name = PaperVOMeta.PASS_SCORE, value = "通过分", required = false, dataTypeClass = BigDecimal.class),
		@ApiImplicitParam(name = PaperVOMeta.JUDGE_R_CNT, value = "判断题数", required = false, dataTypeClass = Integer.class),
		@ApiImplicitParam(name = PaperVOMeta.RADIO_R_CNT, value = "单选题数", required = false, dataTypeClass = Integer.class),
		@ApiImplicitParam(name = PaperVOMeta.CHOICE_R_CNT, value = "多选题数", required = false, dataTypeClass = Integer.class),
		@ApiImplicitParam(name = PaperVOMeta.TEXTAREA_R_CNT, value = "填空题数", required = false, dataTypeClass = Integer.class),
		@ApiImplicitParam(name = PaperVOMeta.QUESTION_MODE, value = "选题策略", required = false, dataTypeClass = String.class),
		@ApiImplicitParam(name = PaperVOMeta.QUESTION_R_CNT, value = "题目总数", required = false, dataTypeClass = Integer.class)
	})
    @ApiOperationSupport(order = 8, author = "金杰 , maillank@qq.com")
    @SentinelResource(value = PaperServiceProxy.QUERY_PAGED_LIST, blockHandlerClass = { SentinelExceptionUtil.class }, blockHandler = SentinelExceptionUtil.HANDLER)
    @PostMapping(PaperServiceProxy.QUERY_PAGED_LIST)
    public Result<PagedList<Paper>> queryPagedList(PaperVO sample) {
        Result<PagedList<Paper>> result = new Result<>();
        PagedList<Paper> list = paperService.queryPagedList(sample, sample.getPageSize(), sample.getPageIndex());
        // join 关联的对象
        paperService.dao().fill(list).with(PaperMeta.LEARN_PAPER).with(PaperMeta.LEARN).execute();
        result.success(true).data(list);
        return result;
    }
}
